package technicalservices.database;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/** Design pattern: Template Method (?) + Polymorphism */
public abstract class Database implements IDatabase {

	// Connection
	private Connection connection;
	private Statement myStatement;
	private ResultSet resultSet;

	/* Load the SQL drivers for Microsoft SQL. */
	protected void loadDriver() {
		try {
			Class.forName(getClassName());
		} catch (ClassNotFoundException ex) {
			System.out.println("ClassNotFound: " + ex);
		}
	}

	@Override
	public void connect(String host, String user, String password, String database, int port) {
		try {
			connection = getConnection(host, user, password, database, port);
			System.out.println("Database connection established...");
		} catch (SQLException e) {
			System.out.println("SQL Exception" + e);
		}
	}

	@Override
	public void close() {
		try {
			connection.close();
		} catch (SQLException ex) {
			// TODO: Log error.
			System.out.println("SQL Close Exception" + ex);
		}
	}

	@Override
	public void executeSQL(String queryString) {
		try {
			createStatement();
			System.out.println("queryString = " + queryString);
			executeQuery(queryString);
		} catch (SQLException ex) {
			// TODO: Log error.
			System.out.println("SQL execute Query Exception" + ex);
		}
	}

	public abstract String getClassName();

	public abstract Connection getConnection(String host, String user, String password, String database, int port) throws SQLException;

	private void createStatement() throws SQLException {
		myStatement = connection.createStatement();
	}

	private void executeQuery(String query) throws SQLException {
		resultSet = myStatement.executeQuery(query);
	}

	/**
	 * @return
	 * @uml.property name="resultSet"
	 */
	public ResultSet getResultSet() {
		return resultSet;
	}

	/**
	 * @return
	 * @uml.property name="connection"
	 */
	public Connection getConnection() {
		return connection;
	}

	public void executeUpdate(String query) throws SQLException {
		createStatement();
		System.out.println("query = " + query);
		int executeUpdate = myStatement.executeUpdate(query);
	}

	/* tableExists(String table) checks whether or not the table exists in the
	 * database
	 * 
	 * @return true if the table exists, false otherwise */
	private boolean tableExists(String table) {
		try {
			DatabaseMetaData md = connection.getMetaData();
			ResultSet tables = md.getTables(null, null, "%", null);
			while (tables.next()) {
				if (tables.getString(3).equals(table)) {
					return true;
				}
			}
		} catch (SQLException ex) {
			return false;
		}
		return false;
	}

	/* Create table */
	private void createTable(String sql) {
		executeSQL(sql);
	}
}
